package cn.nawang.ebeim.api.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Util {

  private static MessageDigest digest = null;

  public Util() {}

  /**
   * 生成随机数
   */
  public static String randomABC(int size) {
    String str = "";
    for (int i = 0; i < size; i++) {
      char c = 'a';
      c = (char) (c + (int) (Math.random() * 26));
      str = str + c;
    }
    return str;
  }

  public synchronized static final String hash(String data) {
    if (digest == null) {
      try {
        digest = MessageDigest.getInstance("MD5");
      } catch (NoSuchAlgorithmException nsae) {
        System.err.println(
            "Failed to load the MD5 MessageDigest. " + "We will be unable to function normally.");
        nsae.printStackTrace();
      }
    }
    digest.update(data.getBytes());
    return encodeHex(digest.digest());
  }

  public static final String encodeHex(byte[] bytes) {
    StringBuffer buf = new StringBuffer(bytes.length * 2);
    int i;

    for (i = 0; i < bytes.length; i++) {
      if (((int) bytes[i] & 0xff) < 0x10) {
        buf.append("0");
      }
      buf.append(Long.toString((int) bytes[i] & 0xff, 16));
    }
    return buf.toString().toUpperCase();
  }

  /**
   * Pseudo-random number generator object for use with randomString(). The Random class is not
   * considered to be cryptographically secure, so only use these random Strings for low to medium
   * security applications.
   */
  private static Random randGen = new Random();

  /**
   * Array of numbers and letters of mixed case. Numbers appear in the list twice so that there is a
   * more equal chance that a number will be picked. We can use the array to get a random number or
   * letter by picking a random array index.
   */
  private static char[] numbersAndLetters =
      ("0123456789abcdefghijklmnopqrstuvwxyz" + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")
          .toCharArray();

  /**
   * 字符串的随机数
   * 
   * @param length the desired length of the random String to return.
   * @return a random String of numbers and letters of the specified length.
   */
  public static final String randomString(int length) {
    if (length < 1) {
      return null;
    }
    // Create a char buffer to put random letters and numbers in.
    char[] randBuffer = new char[length];
    for (int i = 0; i < randBuffer.length; i++) {
      randBuffer[i] = numbersAndLetters[randGen.nextInt(71)];
    }
    return new String(randBuffer);
  }

  /**
   * 整数的随机数
   * 
   * @param max
   * @param incremental
   * @return
   */
  public static final int randomInt(int max, int incremental) {
    return randGen.nextInt(max) + incremental;
  }

  /**
   * 判断是否为数字
   */
  public static boolean isNumeric(String str) {
    Pattern pattern = Pattern.compile("[0-9]*");
    return pattern.matcher(str).matches();
  }

  public static boolean isMobileNO(String mobiles){  
    Pattern p = Pattern.compile("^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$"); 
    Matcher m = p.matcher(mobiles); 
    return m.matches();
  }

  /**
   * 
   * @author fanyb
   * @Description: 判断是否为端口号
   * @param str
   * @return boolean
   * @date Oct 24, 20152:53:03 PM
   *
   * @修改人
   * @修改日期
   */
  public static boolean isPort(String str) {
    Pattern pattern = Pattern.compile(
        "^([0-9]|[1-9]\\d|[1-9]\\d{2}|[1-9]\\d{3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])$");
    return pattern.matcher(str).matches();
  }

  public static boolean isPositiveIntegers(String str) {
    Pattern pattern = Pattern.compile("^[0-9]*[1-9][0-9]*$");
    return pattern.matcher(str).matches();
  }

  public static boolean isPositiveDouble(String str) {
    Pattern pattern = Pattern.compile("^[0-9].*$");
    return pattern.matcher(str).matches();
  }

  /**
   * 验证电子邮箱是否合法
   */
  public static boolean emailFormat(String email) {
    boolean tag = true;
    final String pattern1 =
        "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
    final Pattern pattern = Pattern.compile(pattern1);
    final Matcher mat = pattern.matcher(email);
    if (!mat.find()) {
      tag = false;
    }
    return tag;
  }
  
  /**
   * 
   * @author fanyb
   * @Description: 密码格式限定，至少6位，必须是字母和数字组合
   * @param pwd
   * @return boolean 
   * @date Nov 4, 20154:56:58 PM
   *
   * @修改人 
   * @修改日期
   */
  public static boolean pwdFormat(String pwd) {
    boolean tag = true;
    final String pattern1 =
        "^(?=.*?[a-zA-Z])(?=.*?[0-6])[!\"#$%&'()*+,\\-./:;<=>?@\\[\\\\\\]^_`{|}~A-Za-z0-9]{6,50}$";
    final Pattern pattern = Pattern.compile(pattern1);
    final Matcher mat = pattern.matcher(pwd);
    if (!mat.find()) {
      tag = false;
    }
    return tag;
  }

  public static boolean ipCheck(String text) {
    // 定义正则表达式
    String regex = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\."
        + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
        + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
        + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$";
    // 判断ip地址是否与正则表达式匹配
    if (text.matches(regex)) {
      // 返回判断信息
      return true;
    } else {
      // 返回判断信息
      return false;
    }
  }

  public static final boolean isBlank(Object obj) {
    if (obj == null || "".equals(obj)) {
      return true;
    }
    return false;
  }

  public static final boolean isNotBlank(Object obj) {
    if (obj == null || "".equals(obj)) {
      return false;
    } else {
      return true;
    }
  }

  /**
   *
   * @author fanyb
   * @Description: 比较前台传过来的对象和数据库的对象是否有差，有差则以前台的为准
   * @param obj 前台传过来的对象
   * @param objDatasource 数据库的对象
   * @return Object 修改后的对象
   * @throws Throwable
   * @date Aug 19, 20154:40:59 PM
   *
   * @修改人
   * @修改日期
   */
  public static Object comparisonObject(Object obj, Object objDatasource) throws Throwable {
    // 得到类对象
    Class datasourceCla = (Class) obj.getClass();
    Class datasourceByDatabaseCla = (Class) objDatasource.getClass();

    // 得到类中的所有属性集合
    Field[] ds = datasourceCla.getDeclaredFields();
    Field[] dsDatabase = datasourceByDatabaseCla.getDeclaredFields();
    for (int i = 0; i < ds.length; i++) {
      Field f = ds[i];
      Field fDatabase = dsDatabase[i];
      // 获取属性的名字
      String name = dsDatabase[i].getName();
      // 将属性的首字符大写，方便构造get，set方法
      name = name.substring(0, 1).toUpperCase() + name.substring(1);
      f.setAccessible(true); // 设置些属性是可以访问的
      fDatabase.setAccessible(true);
      Object val = f.get(obj);// 得到此属性的值

      String type = f.getType().toString();// 得到此属性的类型
      if (type.equals("class java.lang.String")) {
        if (val == null) {
          Method m = objDatasource.getClass().getMethod("get" + name);
          String value = (String) m.invoke(objDatasource);
          f.set(obj, value);
        }
      }
      if (type.equals("class java.lang.Integer")) {
        if (val == null) {
          Method m = objDatasource.getClass().getMethod("get" + name);
          Integer value = (Integer) m.invoke(objDatasource);
          f.set(obj, value);
        }
      }
      if (type.equals("class java.lang.Long")) {
        if (val == null) {
          Method m = objDatasource.getClass().getMethod("get" + name);
          Long value = (Long) m.invoke(objDatasource);
          f.set(obj, value);
        }
      }
      if (type.equals("class java.lang.Short")) {
        if (val == null) {
          Method m = objDatasource.getClass().getMethod("get" + name);
          Short value = (Short) m.invoke(objDatasource);
          f.set(obj, value);
        }
      }
      if (type.equals("class java.lang.Double")) {
        if (val == null) {
          Method m = objDatasource.getClass().getMethod("get" + name);
          Double value = (Double) m.invoke(objDatasource);
          f.set(obj, value);
        }
      }
      if (type.equals("class java.lang.Boolean")) {
        if (val == null) {
          Method m = objDatasource.getClass().getMethod("get" + name);
          Boolean value = (Boolean) m.invoke(objDatasource);
          f.set(obj, value);
        }
      }
      if (type.equals("class java.util.Date")) {
        if (val == null) {
          Method m = objDatasource.getClass().getMethod("get" + name);
          Date value = (Date) m.invoke(objDatasource);
          f.set(obj, value);
        }
      }
    }
    return obj;
  }
}
